#include "app_buffer.h"


static pthread_mutex_t lock_initializer = PTHREAD_MUTEX_INITIALIZER;

int app_buffer_init(Buffer *buffer,int size)
{
    //1.分配buffer的内存空间
    buffer->ptr = malloc(size);
    if(!buffer->ptr)
    {
        log_warn("Not enough memory for buffer %p",buffer);
        return -1;
    }

    memcpy(&buffer->lock,&lock_initializer,sizeof(pthread_mutex_t));
    buffer->size = size;
    buffer->start = 0;
    buffer->len = 0;
    log_debug("Buffer %p created",buffer);

    return 0;
}

int app_buffer_read(Buffer * buffer,void *buf,int len)
{
    //错误处理（buffer和buf为非空指针）
    {
        if(!buffer || !buf)
        {
            log_warn("buffer or buf not valid");
            return -1;
        } 
    }

    pthread_mutex_lock(&buffer->lock);
    //判断要读取数据长度的合法性
    if(len > buffer->len)
    {
        len = buffer->len;
    }else if(len == 0)
    {
        pthread_mutex_unlock(&buffer->lock);
        return 0;
    }

    //判断数据是否需要两次来读取（数据存储跨越了环型buffer的头部）
    if(buffer->start + len <= buffer->size)
    {
         //只需读取一次的情况
         memcpy(buf,buffer->ptr+buffer->start,len);
         buffer->start += len;
    }else
    {
        //需要读取两次
        int frist_len = buffer->size - buffer->start; //第一次能读取的长度
        memcpy(buf,buffer->ptr+buffer->start,frist_len);
        int second_len = len - frist_len;
        memcpy(buf+frist_len,buffer->ptr,second_len);
        buffer->start = second_len; 
    }

    buffer->len -=len;
    log_trace("Read compelete:buf[] = %s,buffer->len = %d buffer->start = %d",buf,buffer->len,buffer->start);
    pthread_mutex_unlock(&buffer->lock);
    return len;
}

int app_buffer_write(Buffer *buffer,void *buf,int len)
{
    //错误处理（buffer和buf为非空指针）
    
    if(!buffer || !buf)
    {
        log_warn("buffer or buf not valid");
        return -1;
    } 
      

    pthread_mutex_lock(&buffer->lock);

    //判断要写的数据长度是否大于剩余长度
    int remain_len = buffer->size - buffer->len;
    if(len > remain_len)
    {   
        //剩余buffer不足
        log_warn("Insufficient remaining buffer");
        pthread_mutex_unlock(&buffer->lock);
        return -1;
    }

    //确定写入的起始地址
    int write_offset = buffer->start + buffer->len; //写入的起始地址
    if(write_offset > buffer->size)
    {
        //修正写入的起始地址
        write_offset -= buffer->size;
    }

    //判断数据是否需要分次写入
    if((write_offset+len) > buffer->size)
    {
        //需要分两次写入
        int frist_len = buffer->size-write_offset;
        memcpy(buffer->ptr+write_offset,buf,frist_len);
        memcpy(buffer->ptr,buf+frist_len,len-frist_len);
    }
    else
    {
        //一次就能写入
        memcpy(buffer->ptr+write_offset,buf,len);
    }
    buffer->len += len;
    pthread_mutex_unlock(&buffer->lock);
    log_trace("Write compelete:buffer->ptr[] = %s,buffer->len = %d buffer->start = %d",buffer->ptr,buffer->len,buffer->start);
    return len;
}

void app_buffer_close(Buffer *buffer)
{
    if(buffer->ptr)
    {
        free(buffer->ptr);
        buffer->ptr = NULL;
    }
    buffer->len = 0;
    buffer->start = 0;
    buffer->size = 0;
}
